package slog

import (
	"io"
	"os"
	"strings"
	"time"

	"gitee.com/xiawucha365/sago.v2/core/config"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)



type Log struct {
	logger *zap.SugaredLogger

}

func NewLog(cf *config.Config) *Log {

	encoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
		MessageKey: "msg",
		LevelKey:   "level",
		StacktraceKey:  "stacktrace",
		EncodeLevel: zapcore.LowercaseColorLevelEncoder,
		TimeKey:     "time",
		EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
			enc.AppendString(t.Format("2006-01-02 15:04:05"))
		},
		CallerKey:    "linenum",
		EncodeCaller: zapcore.ShortCallerEncoder, // 全路径编码器
		EncodeName:   zapcore.FullNameEncoder,
		EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
			enc.AppendInt64(int64(d) / 1000000)
		},
	})

	//	caller := zap.AddCaller()


	// 实现两个判断日志等级的interface
	//infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
	//	return lvl >= zapcore.InfoLevel
	//})
	//
	//errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
	//	return lvl >= zapcore.ErrorLevel
	//})

	atomicLevel := zap.NewAtomicLevel()
	atomicLevel.SetLevel(zap.InfoLevel)
	atomicLevelSelf := zap.NewAtomicLevel()
	if cf.Log.Level == ""{
		atomicLevelSelf.SetLevel(zap.InfoLevel)
	}else{
		if cf.Log.Level == "info" {
			atomicLevelSelf.SetLevel(zap.InfoLevel)
		}
		if cf.Log.Level == "error" {
			atomicLevelSelf.SetLevel(zap.ErrorLevel)
		}

	}

	// 获取 info、error日志文件的io.Writer 抽象 getWriter() 在下方实现
	//infoWriter := getWriter(cf,cf.Log.LogDir + "/runtime.log")
	//errorWriter := getWriter(cf,cf.Log.LogDir + "/runtime.log")

	writer := getWriter(cf, cf.Log.LogDir+"/runtime.log")

	filed := zap.Fields(zap.String("ip", "10.10.222.33"))
	// 最后创建具体的Logger
	core := zapcore.NewTee(
		//zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel),
		zapcore.NewCore(encoder, zapcore.AddSync(writer), atomicLevelSelf),
		zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), atomicLevel),
		//zapcore.NewCore(
		//		encoder,                                           // 编码器配置
		//		zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印到控制台和文件
		//		atomicLevel,                                                                     // 日志级别
		//	),
	)

	//	// 开启文件及行号
	//development := zap.Development()
	logger2 := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1), filed) // 需要传入 zap.AddCaller() 才会显示打日志点的文件名和行数, 有点小坑
	//logger2.Sugar().Sync()
	//log.Info("ingo....")
	//log.Error("errr")
	//log.Warn("waning dsdsd")

	return &Log{logger: logger2.Sugar()}
}

func getWriter(cf *config.Config, filename string) io.Writer {
	datetime := ""
	if cf.Log.SplitDuration == LogSpitDay {
		datetime = "_" + time.Now().Format("20060102") //后面的参数是固定的 否则将无法正常输出
	} else if cf.Log.SplitDuration == LogSpitMonth {
		datetime = "_" + time.Now().Format("200601") //后面的参数是固定的 否则将无法正常输出
	}
	filename = strings.Replace(filename, ".log", "", -1) + datetime + ".log"
	// 生成rotatelogs的Logger 实际生成的文件名 demo.log.YYmmddHH
	// demo.log是指向最新日志的链接
	// 保存7天内的日志，每1小时(整点)分割一次日志
	hook, err := rotatelogs.New(
		filename,
		//, // 没有使用go风格反人类的format格式
		//rotatelogs.WithLinkName(filename),
		rotatelogs.WithMaxAge(time.Hour*24*time.Duration(cf.Log.MaxAge)),
		//rotatelogs.WithRotationTime(time.Hour),
	)

	if err != nil {
		panic(err)
	}
	return hook
}

func (l *Log) Info(args ...interface{}) {
	l.logger.Info(args)
}

func (l *Log) Infof(template string, args ...interface{}) {
	l.logger.Infof(template, args)
}

func (l *Log) Error(args ...interface{}) {
	l.logger.Error(args)
}

func (l *Log) Errorf(template string, args ...interface{}) {
	l.logger.Errorf(template, args)
}

func (l *Log) Warn(args ...interface{}) {
	l.logger.Warn(args)
}

func (l *Log) Warnf(template string, args ...interface{}) {
	l.logger.Warnf(template, args)
}

func (l *Log) Panic(args ...interface{}) {
	l.logger.Panic(args)
}

func (l *Log) Panicf(template string, args ...interface{}) {
	l.logger.Panicf(template, args)
}

func (l *Log) Debug(args ...interface{}) {
	l.logger.Debug(args)
}

func (l *Log) Debugf(template string, args ...interface{}) {
	l.logger.Debugf(template, args)
}


func (l *Log) Sync() error {
	return l.logger.Sync()
}
//
//func log(cf *config.Config)  {
//
//	hook := lumberjack.Logger{
//		Filename:   "./spikeProxy1.log", // 日志文件路径
//		MaxSize:    128,                      // 每个日志文件保存的最大尺寸 单位：M
//		MaxBackups: 3,                       // 日志文件最多保存多少个备份
//		MaxAge:     7,                        // 文件最多保存多少天
//		Compress:   true,                     // 是否压缩
//	}
//
//	encoderConfig := zapcore.EncoderConfig{
//		TimeKey:        "time",
//		LevelKey:       "level",
//		NameKey:        "logger",
//		CallerKey:      "linenum",
//		MessageKey:     "msg",
//		StacktraceKey:  "stacktrace",
//		LineEnding:     zapcore.DefaultLineEnding,
//		EncodeLevel:    zapcore.LowercaseLevelEncoder,  // 小写编码器
//		EncodeTime:     zapcore.ISO8601TimeEncoder,     // ISO8601 UTC 时间格式
//		EncodeDuration: zapcore.SecondsDurationEncoder, //
//		EncodeCaller:   zapcore.FullCallerEncoder,      // 全路径编码器
//		EncodeName:     zapcore.FullNameEncoder,
//	}
//
//	// 设置日志级别
//	atomicLevel := zap.NewAtomicLevel()
//	atomicLevel.SetLevel(zap.InfoLevel)
//
//	core := zapcore.NewCore(
//		zapcore.NewJSONEncoder(encoderConfig),                                           // 编码器配置
//		zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印到控制台和文件
//		atomicLevel,                                                                     // 日志级别
//	)
//
//	// 开启开发模式，堆栈跟踪
//	caller := zap.AddCaller()
//	// 开启文件及行号
//	development := zap.Development()
//	// 设置初始化字段
//	filed := zap.Fields(zap.String("server", "10.10.222.33"))
//	// 构造日志
//	logger := zap.New(core, caller, development, filed)
//
//	logger.Info("log 初始化成功")
//
//	logger.Error("error")
//	logger.Panic("waning")
//	logger.Info("无法获取网址",
//		zap.String("url", "http://www.baidu.com"),
//		zap.Int("attempt", 3),
//		zap.Duration("backoff", time.Second))
//}
//
//func log2()  {
//	// 设置一些基本日志格式 具体含义还比较好理解，直接看zap源码也不难懂
//	encoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
//		MessageKey:  "msg",
//		LevelKey:    "level",
//		//StacktraceKey:  "stacktrace",
//		EncodeLevel: zapcore.CapitalLevelEncoder,
//		TimeKey:     "time",
//		EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
//			enc.AppendString(t.Format("2006-01-02 15:04:05"))
//		},
//		CallerKey:    "linenum",
//		EncodeCaller:   zapcore.FullCallerEncoder,      // 全路径编码器
//		//EncodeName:     zapcore.FullNameEncoder,
//		EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
//			enc.AppendInt64(int64(d) / 1000000)
//		},
//	})
//
//	// 实现两个判断日志等级的interface
//	infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
//		return lvl >= zapcore.InfoLevel
//	})
//
//	errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
//		return lvl >= zapcore.ErrorLevel
//	})
//
//	// 获取 info、error日志文件的io.Writer 抽象 getWriter() 在下方实现
//	infoWriter := getWriter("./runtime.log")
//	errorWriter := getWriter("./demo_error.log")
//
//	// 最后创建具体的Logger
//	core := zapcore.NewTee(
//		zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel),
//		zapcore.NewCore(encoder, zapcore.AddSync(errorWriter), errorLevel),
//	)
//
//	log := zap.New(core, zap.AddCaller()).Sugar() // 需要传入 zap.AddCaller() 才会显示打日志点的文件名和行数, 有点小坑
//	log.Info("ingo....")
//	log.Error("errr")
//	log.Warn("waning dsdsd")
//	//log.Panic("panic")
//}
//
//func getWriter(filename string) io.Writer {
//	datetime := time.Now().Format("20060102")//后面的参数是固定的 否则将无法正常输出
//	filename = strings.Replace(filename, ".log", "", -1)+"_"+datetime+".log"
//	// 生成rotatelogs的Logger 实际生成的文件名 demo.log.YYmmddHH
//	// demo.log是指向最新日志的链接
//	// 保存7天内的日志，每1小时(整点)分割一次日志
//	hook, err := rotatelogs.New(
//		filename,
//		//, // 没有使用go风格反人类的format格式
//		//rotatelogs.WithLinkName(filename),
//		//rotatelogs.WithMaxAge(time.Hour*24*7),
//		//rotatelogs.WithRotationTime(time.Hour),
//	)
//
//	if err != nil {
//		panic(err)
//	}
//	return hook
//}
